# -*- coding: utf-8 -*-
#
import sys
import numpy as np

from qwt.qt.QtGui import (QApplication, QPen, QBrush, QFrame, QFont, QPainter,
                          QPaintEngine)
from qwt.qt.QtCore import QSize
from qwt.qt.QtCore import Qt
from qwt import (QwtLegend, QwtLegendData, QwtScaleMap, QwtText, QwtPlot, QwtPlotMarker, QwtPlotItem, 
                QwtPlotGrid, QwtPlotCurve, QwtPlotMarker, QwtSymbol)

from uidef import *

# 绘图体系设计：
# - VSPlot负责将QwtPlot的所有工作，包括数据准备等
# - VSChart负责提供缩放，Qt槽的更新等
# - VSApp负责提供通信和Qt信号的发送

# 默认的曲线绘制颜色列表
DEFAULT_CURVE_COLORS=(
    Qt.blue, Qt.red, Qt.green, Qt.white, Qt.yellow, 
    Qt.cyan, Qt.magenta, Qt.gray, Qt.red, Qt.green, 
    Qt.yellow, Qt.cyan, Qt.white, Qt.magenta, Qt.gray
)

# QwtPlot.Axis aliases
Y1 = Left   = QwtPlot.yLeft
Y2 = Right  = QwtPlot.yRight
X1 = Bottom = QwtPlot.xBottom
X2 = Top    = QwtPlot.xTop

symbol_table=(QwtSymbol.NoSymbol, QwtSymbol.Rect, QwtSymbol.Ellipse, QwtSymbol.Diamond)

def get_curve_cfg(c):
    """
    @brief 
    """
    ret = list(DEFAULT_CURVE_CONFIG)
    for i in range(len(c)):
        ret[i] = c[i]
    return ret

# VSPlot 提供多个曲线的合并及其数据管理工作
# 包含legend，Symbol等
#

class VSPlot(QwtPlot):
    "Supply a generic base class for Multi-Curve chart"
    def __init__(self, title, sconfig=DEFAULT_VSCHART_CFG):
        super().__init__(title)
        self.flags = {'xuse_s': False, 'auto_refresh': True} # X轴是否使用距离
        self.s = []
        self.curves = []
        self.timestamp = []
        self.datas = []
        self.data_op = []
        self.load_config(sconfig)
    
    def load_config(self, scfg):
        self.pencolors = tuple(scfg.get('curve_color', DEFAULT_CURVE_COLORS))
        self.width = scfg.get('width', DEFAULT_PLOT_WIDTH)
        assert(len(scfg['y_range']) >= 2)
        self.setAxisTitle(Y1, scfg['y_name'][0])
        self.setAxisTitle(Y2, scfg['y_name'][1])
        self.curve_num = scfg['curve_num']
        
        # setup UI settings
        # 设置坐标轴
        self.enableAxis(Y2)
        self.setAxisAutoScale(Y1)
        self.setAxisAutoScale(Y2)
        self.setAxisAutoScale(X1)
        if self.flags['xuse_s']:
            self.setAxisTitle(X1, XAXIS_TITLE[1])
        else:
            self.setAxisTitle(X1, XAXIS_TITLE[0])
        # 设置图例
        legend = QwtLegend()
        legend.setDefaultItemMode(QwtLegendData.Checkable)
        self.insertLegend(legend, QwtPlot.RightLegend)
        legend.checked.connect(self.showCurve)
        # 设置网格
        grid = QwtPlotGrid()
        grid.attach(self)
        grid.setPen(QPen(Qt.white, 0, Qt.DotLine))
        self.plotLayout().setAlignCanvasToScales(True)                
        self.load_curve_config(scfg['curve_cfg'])

    def add_curve(self, i, cfg):
        cv = QwtPlotCurve(cfg[ICURVE_NAME])
        self.data_op.append(cfg[ICURVE_BASE:ICURVE_SCALE])
        self.datas.append([])
        if cfg[ICURVE_LOCATE] == LOCATE_Y2: # 设置次坐标轴
            cv.setYAxis(Y2)
        style = cfg[ICURVE_STYLE] 
        if  style == STYLE_NOSYMBOL:    # 选择普通颜色，或选择样式(无，方块，圆，菱形)
            cv.setPen(QPen(self.pencolors[i]))
        else:
            cv.setSymbol(QwtSymbol(symbol_table[style], QBrush(), self.pencolors[i], 3))
        cv.attach(self)
        self.curves.append(cv)  # 便于后续操作

    def load_curve_config(self, cvcfg):
        for i in range(len(cvcfg)):
            self.add_curve(i, get_curve_cfg(cvcfg[i]))

    def showCurve(self, item, on, index=None):
        item.setVisible(on)
        self.legend().legendWidget(item).setChecked(on)
        self.replot()

    def refresh(self):
        self.setAutoReplot()

    def update_curve_data(self):
        print("len", len(self.s), len(self.datas[0]))
        for i in range(self.curve_num):
            self.curves[i].setData(self.s, self.datas[i])

    def push_unit_data(self, s, items):
        self.s.append(s)
        assert(len(items) == self.curve_num)
        for i in range(len(items)):
            self.datas[i].append(items[i])

    def push_all_curve(self, s, items):
        self.s = s
        assert(len(items) == self.curve_num)
        for i in range(len(items)):
            self.datas[i] = items[i]
            print('items', s, items[i])
            self.curves[i].setData(s, self.datas[i])
        
        self.setAutoReplot()

    def push_samples(self):
        self.xval = np.arange(800)
        phase = 5
        self.yval = np.sin(self.xval - phase)
        self.zval = np.cos(3*(self.xval + phase))
        self.s.extend(self.xval)
        self.datas[0].extend(self.yval)
        self.datas[1].extend(self.yval*2)
        self.datas[2].extend(self.zval)
        #self.curves[0].setData(self.xval, self.yval)
        #self.curves[1].setData(self.xval, self.yval*2)
        #self.curves[2].setData(self.xval, self.zval)

def make():
    demo = VSPlot('Test')
    demo.resize(800, 600)
    demo.push_samples()
    demo.push_unit_data(800, (1, 2, 3))
    demo.update_curve_data()
    demo.show()
    return demo

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = make()
    sys.exit(app.exec_())

